# build the package
os = require 'os'
fs = require 'fs-extra'
fsp = require '../libs/fs-promises'
path = require 'path'
pr = path.resolve
_ = require 'underscore'
build = require '../libs/build-request'
request = require 'request'
zip = require '../libs/zip'
Q = require 'q'
bodyParser = require 'body-parser'

requestp = Q.denodeify(request)
#create a json parser
#jsonParser ＝ bodyParser.json()
# 文件夹合并复制
fs_merge_promise = (src, dest, exclude) ->
  fsp.traverse_safe src, relative: true
  .then (all) ->
    all_promises = _.map all, (each) ->
      if (exclude && (new RegExp("#{exclude}$")).test(each.toLowerCase()))
        return ;
      fsp.copy path.resolve(src, each), path.resolve(dest, each)
    Q.all all_promises

curl_promise = (url, dest) ->
  requestp(url)
  .then (args) -> body = args[1]
  .then (body) ->
    fsp.outputFile dest, body

# 负责公用的打包过程, 需要注意的是打包的是沙箱中的文件，所以没有生成的文件需要提前生成
# bundleIdentifier - 包Id
# sandbox_path - 沙箱路径
# baseUrl - 如果需要动态请求资源该如何
# pages - 哪些页面json，参数不带后缀，在服务器上，沙箱内的json配置文件并不一定和数据库是同步的，打包时需要重新请求
# tempProject - 临时工程名
module.exports = (bundleIdentifier, sandbox_path, baseUrl, page_names, tempProject, req, res) ->
  # tempProject 压缩后保存的位置
  tempZipProject = "#{tempProject}.zip"
  # es6特性
  promise = new Promise (resolve, reject) ->
    resolve()
  .then ->
    console.log "清理临时目录：#{tempProject}"
    console.log "清理临时zip：#{tempZipProject}"
    Q.all [
      fsp.remove tempProject
      fsp.remove tempZipProject
    ]
    .then ->
      console.log "重新生成临时目录：#{tempProject}"
      fsp.mkdirs tempProject
    .then ->
      #3 复制static/runtime和static/vendor目录
      static_dir = "static"
      if process.env.NODE_ENV == 'production'
        static_dir = "static-dist"
      if req.body.mode == 'production'
        console.log "生产模式，仅复制压缩后的文件"
        prod_res = ['css/runtime.00abec.min.css', 'css/runtime.0080fc.min.css',
         'css/runtime.06c1ae.min.css', 'css/runtime.f7f6f7.min.css',
         'css/runtime.fb4747.min.css', 'css/runtime.ff6633.min.css',
         'css/runtime.min.css', 'fonts', 'images',
         'js/require.min.js', 'js/bootstrap.build.min.js',
         'js/extension-library.js', 'fonts/load.svg']
        prod_vendor = ['require-css/css.min.js', 'requirejs-text/text.js',
        'slick.js/slick/slick-theme.css', 'slick.js/slick/slick.css']

        ps = _.chain(prod_res).map (each) ->
                fsp.copy path.resolve('.', "#{static_dir}/runtime/#{each}"), "#{tempProject}/runtime/#{each}"
              .value()
        tmp = _.chain(prod_vendor).map (each) ->
                fsp.copy path.resolve('.', "#{static_dir}/vendor/#{each}"), "#{tempProject}/vendor/#{each}"
              .value()
        ps = ps.concat tmp
        # insert a promise for create dirs
        ps.unshift fsp.mkdirs "#{tempProject}/runtime"
        ps.unshift fsp.mkdirs "#{tempProject}/vendor"
        Q.all ps
      else
        console.log "复制runtime，vendor目录"
        Q.all [
          fsp.copy path.resolve('.', "#{static_dir}/runtime"), "#{tempProject}/runtime"
          fsp.copy path.resolve('.', "#{static_dir}/vendor"), "#{tempProject}/vendor"
        ]
    .then ->
      # 2 复制project下所有文件到临时目录
      console.log "复制project下所有文件到临时目录"
      Q.all [
        fs_merge_promise pr(sandbox_path, 'js'), pr(tempProject, 'runtime', 'js'), "json"
        fs_merge_promise pr(sandbox_path, 'images'), pr(tempProject, 'images')
        fs_merge_promise pr(sandbox_path, 'fonts'), pr(tempProject, 'fonts')
      ]

      #请求每个页面的json配置
      json_promises = _.map page_names, (each) ->
        curl_promise("#{baseUrl}/runtime/js/pages/#{each}.json", "#{tempProject}/runtime/js/pages/#{each}.json")
      Q.all json_promises
    .then ->
      # 编译less
      console.log "编译less"
      fsp.traverse_safe pr(sandbox_path, 'less'), relative: true
      .then (styles) ->
        _.chain(styles).filter (file) ->
          !file.startsWith('_') and file.endsWith('.less')
        .map (style) ->
          style.replace('.less', '.css')
        .value()
      .then (css_names) ->
        css_promises = _.map css_names, (each) ->
          curl_promise("#{baseUrl}/css/#{each}", "#{tempProject}/css/#{each}")
        Q.all css_promises
    .then ->
      # 生成index.html
      # 生成app.js
      # 覆盖默认extension-library.js
      console.log "生成index.html, app.js"
      Q.all [
        # 每个页面ID都生成一个html，与index.html一模一样...
        curl_promise("#{baseUrl}/index.html", "#{tempProject}/index.html")
        .then ->
          page_promises = _.map page_names, (each) ->
            fsp.copy "#{tempProject}/index.html", "#{tempProject}/#{each}.html" unless each.toLocaleLowerCase() == 'index'
          # do all
          Q.all page_promises

        curl_promise("#{baseUrl}/app.js", "#{tempProject}/app.js")
        curl_promise("#{baseUrl}/runtime/js/extension-library.js", "#{tempProject}/runtime/js/extension-library.js")
      ]
    .then -> # 8 压缩文件
      console.log "开始压缩轻应用app"
      zip(tempProject, tempZipProject)
    .then -> # 9 快速编译
      if req.body.platform == 'zip'
        console.log "start downloading zip"
        stream = fs.readFileSync tempZipProject
        res.set('Content-Type', 'application/octet-stream')
        .set('Content-Disposition', "attachment; filename=\"#{encodeURI(req.body.title)}.zip\"")
        .status(200).send(stream)
      else
        console.log "连接puzzle在线打包..."
        build(tempZipProject, {title: req.body.title, platform: req.body.platform, bundleIdentifier: bundleIdentifier})
    .then (job) ->
      new Promise (resolve, reject) ->
        if req.body.platform != 'zip'
          res.status(200).send(job) # TODO 可根据job来轮询或者用socket.io
        resolve()
    # .then ->
    #   console.log "清理临时目录：#{tempProject}"
    #   fsp.remove tempProject
    # .then ->
    #   console.log "清理临时zip：#{tempZipProject}"
    #   fsp.remove tempZipProject]
